#!/usr/bin/env python
# @Author  : Bright (brt2@qq.com)
# @Create  : 2022-01-03
# @Update  : 0.3.1 / 2024-12-02

# https://www.sublimetext.com/docs/api_reference.html

import sublime
import sublime_plugin

import os.path
import subprocess
from io import BytesIO

from base64 import b64encode
from hashlib import md5
from datetime import datetime
from urllib.request import urlopen
from PIL import Image

from .formatter.md_fmt import MarkdownFormatter

def md5sum(data, salt=None):
    if salt is None:
        salt = str(datetime.now()).encode()

    md5obj = md5(salt)
    md5obj.update(data)
    return md5obj.hexdigest()

class NotSavedFile(Exception): pass
class NotMarkdownFile(Exception): pass
class NotUpdateLatest(Exception): pass
class NoConfigFile(Exception): pass

class MdFormatCommand(sublime_plugin.TextCommand):

    fmt = MarkdownFormatter()

    def __init__(self, *args, **kwgs):
        super().__init__(*args, **kwgs)
        # print(">>> 初始化MdFormatCommand")
        self.settings = sublime.load_settings('settings.sublime-settings')

    def run(self, edit, type):
        {
            "hugo_format": self.hugo_format,
            "call_mdformat": self.call_mdformat,
            "img2local": self.img2local
        }[type](edit)

    def _reload_doc(self):
        if self.view.is_dirty():
            if not sublime.ok_cancel_dialog("是否保存"):
                raise NotSavedFile()
            self.view.run_command('save')

        path_currfile = self.view.file_name()
        _, ext = os.path.splitext(path_currfile)
        if ext != ".md":
            # sublime.error_message("")
            # sublime.message_dialog("")
            if not sublime.ok_cancel_dialog("当前文档非.md文档，是否继续"):
                raise NotMarkdownFile()
        self.fmt.load_file(path_currfile)

    def hugo_format(self, edit):
        self._reload_doc()

        # 传入文档路径的list，作为category
        # self.fmt.metadata['categories'] = get_categories(self.fmt.file_path,
        #                                   self.settings.get("blog_dir_name", ""))
        self.fmt.format()
        self.fmt.overwrite()

    def call_mdformat(self, edit):
        # import mdformat

        path_currfile = self.view.file_name()
        print('>>> mdformat "{}"'.format(path_currfile))
        # mdformat.file(path_currfile)
        # try:
        #     output = subprocess.check_output(["python", "-m", "mdformat", path_currfile])
        #     print(output.decode())
        # except subprocess.CalledProcessError as e:
        #     print("Command failed with exit code", e.returncode)
        #     print("Output: ", e.output.decode())
        subprocess.call(["python", "-m", "mdformat", path_currfile], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    def img2local(self, edit):
        self._reload_doc()

        # dict_images = self.fmt.get_images("local")
        dict_images = self.fmt.get_images("http", force_abspath=False, ignore_websites=None)

        self.fmt.unlock_text()
        for line_idx, url_img in dict_images.items():
            path_img = os.path.join(os.path.dirname(self.fmt.file_path), os.path.basename(url_img))
            _, ext = os.path.splitext(path_img)
            if ext != ".webp":
                path_img += ".webp"

            if not os.path.exists(path_img):
                try:
                    with urlopen(url_img) as resp, open(path_img, 'wb') as fp:
                        img_buff = resp.read()
                        if ext == ".webp":
                            fp.write(img_buff)
                        else:
                            img = Image.open(BytesIO(img_buff))
                            img.save(path_img, "webp")

                except Exception as e:
                    print("[-] Download image {} failed: {}".format(url_img, e))
                    continue

            relpath = os.path.relpath(path_img, os.path.dirname(self.fmt.file_path))
            num_space = self.fmt.get_text()[line_idx].find("!")
            indent = " "*num_space
            self.fmt.modify_text(line_idx, "{}![]({})".format(indent, relpath))

        self.fmt.overwrite()

    def img2base64(self, edit):
        self._reload_doc()

        dict_images = self.fmt.get_images("local")
        # self.fmt.process_images(dict_images, lambda xxx: pass)
        self.fmt.unlock_text()
        for line_idx, path_img in dict_images.items():
            with open(path_img, "rb") as fp:
                img_buff = fp.read()
                img_base64 = b64encode(img_buff)  # bytes

            tmp_label = md5sum(img_buff[:70])
            num_space = self.fmt.get_text()[line_idx].find("!")
            indent = " "*num_space
            self.fmt.modify_text(line_idx, "{}[{}]:data:image/png;base64,{}\n{}![][{}]".format(
                    indent, tmp_label, img_base64.decode(), indent, tmp_label
                ))

        dict_images = self.fmt.get_images("http")
        self.fmt.unlock_text()
        for line_idx, url_img in dict_images.items():
            resp = urlopen(url_img)
            img_buff = resp.read()
            img_base64 = b64encode(img_buff)  # bytes

            tmp_label = md5sum(img_buff[:70])
            num_space = self.fmt.get_text()[line_idx].find("!")
            indent = " "*num_space
            self.fmt.modify_text(line_idx, "{}[{}]:data:image/png;base64,{}\n{}![][{}]".format(
                    indent, tmp_label, img_base64.decode(), indent, tmp_label
                ))

        self.fmt.overwrite()
